using namespace std;
#include<iostream>
#include<future> // 类模板：保存异步结果
#include<memory>
#include<thread>
#include<utility>

int Add(const int x, const int y, const string& flag)
{
    cout << flag << " > " << this_thread::get_id() << endl;
    return  x + y;
}


int main()
{
    cout << "main thread_id = " << this_thread::get_id() << endl << endl;

    // ----------------- async ------------------------------------- 函数模板 

    // shared_future<int> fu1 = async(launch::async, Add, 1, 2, "fu1"); 右值移动 
    future<int> fu1 = async(launch::async, Add, 1, 2, "fu1"); // launch::async 创建新线程异步

    // std::future 适用于单一消费，一次get() 后结果被移动到调用者，无法再次获取
    shared_future<int> fu1_result_copy = fu1.share(); // 结果复制，多次获取 或者 move(fu1)
    
    cout << fu1_result_copy.get() << endl << endl;

    shared_future<int> fu2 = async(launch::deferred, Add, 2, 3, "fu2"); // 同步
    cout << "get fu2 result start..." << endl;
    this_thread::sleep_for(chrono::seconds(2));
    cout << fu2.get() << endl;

    // -----------------------------------------------------------------


    // -------------------- packaged_task ------------------------------ 类模板 : 唯一执行权
    // 类似于 functional , 把包装的任务丢给另一个线程执行
    packaged_task<int(int, int, const string&)> task(Add);
    shared_future<int> fu3 = task.get_future();

    thread th_1(move(task), 3, 4, "fu3");
    th_1.join();

    cout << fu3.get() << " " << fu3.get() << endl;

    // ------------------------------------------------------------------


    // ---------------------- promise -----------------------------------类模板：唯一执行权 在任意地方通过 promise 设置结果，无需绑定具体任务
    promise<int> prom;
    shared_future<int> fu4 = prom.get_future();

    thread th_2([fu4]{
        cout << "promise: " << fu4.get() << endl;
    });

    this_thread::sleep_for(chrono::seconds(3));
    prom.set_value(100);
    th_2.join();

    return 0;
}